﻿/**
 * Copyright (C), 2015-2045, Jimu
 *
 * File:         can_parse.c 
 * Description:  通过配置文件从汽车CAN总线中获取汽车信号, 已经通过硬线获取汽车信号   
 * Others:
 * History:
 * - V0.1, 2018.06.19, LongLan
 *    Initial version
 */
#define CANI_VERSION  0x01


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <limits.h>
#include "can_parse.h"
#include "xmlparser.h"
#ifdef WIN32
#include <afxmt.h>
#else
#include <pthread.h>
#include <sys/ioctl.h>
#endif


#undef  pr_err
#define pr_err(fmt, ...)      printf("can parse: "fmt, ##__VA_ARGS__)

#ifdef WIN32
#define pthread_mutex_lock(lock_p)    signal_common.signal_mutex.Lock()
#define pthread_mutex_unlock(lock_p)  signal_common.signal_mutex.Unlock()
#define pthread_mutex_t  CCriticalSection
#endif

#define CAN_ALIVE_TIMEOUT  1500  /* ms, CAN活动超时时间 */
#define CAN_DETECT_DELAY   3000  /* CAN通信诊断延时, 从上电后超过该时间未收到CAN报文, 认为CAN掉线 */

/* 
 * 控制报文(标准数据帧), 用于和CAN转换盒握手, 主机和转换盒使用固定的500Kbps波特率 
 * CAN转换盒上电后周期发送2个控制报文, 主机接收到报文后选取一个控制报文作为握手报文, 
 * 并使用该报文发送配置信息
*/
#define CTRL_MSG1  0x000
#define CTRL_MSG2  0x7EF

struct key_word_t {
	const char *name;
	int  value;
};

struct key_map {
	const char *sig_name;
	int *val_p;
	int default_value;  /* 外部无法提供信号时的缺省值 */
	unsigned int init_status;
};

#define LIST_COUNT  32
typedef struct {
	#define SIG_ANALOG  0x01  /* 模拟信号 */
	#define SIG_SIGNED  0x02  /* 有符号模拟信号 */
	#define SIG_FLASH   0x04  /* 闪烁信号， 主要用于转向灯 */
	#define SIG_HARD_LINE 0x08  /* 使用汽车硬线检测信号 */
	unsigned int status;      /* -1:无效信号配置, 0:离散信号, 1:连续无符号信号， 2：连续有符号信号 */
	uint32_t id;   /* CAN ID, bit31表示是否为扩展帧 */
    int startbit;
	int bits;
	int offset;
	int min;
	int max;
	int mult;
	int div;
	int list_count;
	int inlist[LIST_COUNT];
	int outlist[LIST_COUNT];
	int timeout;  /* ms，信号超时时间 */
	int current_counter;  /* 超时计时器 */
	int flash_interval;   /* ms, 闪烁间隔 */
	int flash_counter;    /* 闪烁计时器 */
	int invalid_value;
	int *val_p;
} sig_cfg_t;


#define EXTERN_MSGS  16
struct sig_global {
	int valid;
	pthread_mutex_t  signal_mutex;  /* 用于获取信号的互斥锁 */
	int bitrate;
	int big_endian;  /* 0:little-endian, 1:big-endian */
	int sig_count;
	sig_cfg_t *cfg_list;
	int no_can;
	int canbox_valid;
	unsigned int boxid;
	unsigned int ctrl_id;
	int can_detect_delay;
	int can_alive_counter;
	int hard_valid;

	sig_cfg_t *hard_left;
	sig_cfg_t *hard_right;
	sig_cfg_t *hard_brake;
	sig_cfg_t *hard_speed;

	struct signal_operations sig_op;
	int  extern_msg_count;
	uint32_t extern_msgs[EXTERN_MSGS];
};



#define MEMBER_ADDR(member) (&(car_signal.member) )


signal_t  car_signal;

static const struct key_map keystring[] = {
	{"speed",           MEMBER_ADDR(speed),          -1,  SIG_ANALOG},
	{"brake",           MEMBER_ADDR(brake),          -1,  0},
	{"reverse",         MEMBER_ADDR(reverse),        -1,  0},
	{"left_light",      MEMBER_ADDR(left_light),     -1,  0},
	{"right_light",     MEMBER_ADDR(right_light),    -1,  0},
	{"steering_angle",  MEMBER_ADDR(steering_angle),  SIG_IVALID,  SIG_ANALOG},
	{"steering_speed",  MEMBER_ADDR(steering_speed), -1,     SIG_ANALOG},
	{"ldw_on",          MEMBER_ADDR(ldw_on),         -1,  0},
	{"fcw_on",          MEMBER_ADDR(fcw_on),         -1,  0},
	{"low_beam",        MEMBER_ADDR(low_beam),       -1,  0},
	{"high_beam",       MEMBER_ADDR(high_beam),      -1,  0},
	{"front_wiper",     MEMBER_ADDR(front_wiper),    -1,  0},
	{"yaw_rate",        MEMBER_ADDR(yaw_rate),        SIG_IVALID,  SIG_ANALOG},
	{"standstill",      MEMBER_ADDR(standstill),     -1,  0},
};



static struct sig_global signal_common = {0,};


/* 定义内置的关键字 */
#define other  -1
#define keep   -100
#define adj    2

static const struct key_word_t  built_key[] = {
	{"other",   other},
	{"keep",    keep},
	{"adj",     adj},
};



const char* section_getstring(const dictionary * d, const char * section, const char * key, const char* notfound)
{
	char buf[128];

	strncpy(buf, section, 60);
	strcat(buf, ":");
	strncat(buf, key, 60);
    return xmlparser_getstring(d, buf, notfound);
}

#define ARRAY_UNIT(array) (sizeof(array) / sizeof(array[0]))

static char   *strlist_scan(const char *input, char *substring)
{
	if (input == NULL || substring == NULL)
		return NULL;
	while (*input != '\0' && isspace(*input) )
		input++;
	
	while (*input != '\0' && (!isspace(*input)) ) 
		*substring++ = *input++;
	*substring = '\0';
	return (*input == '\0')? NULL : (char*)input;
}

static int    strings_int(const char *strlist, int array[], int capacity)
{
	int count, i;
	char *s, *end, tmp[256];

	if (array == NULL)
		return 0;
	
    s = (char*)strlist;
	count = 0;
    while (s != NULL && count < capacity)
	{
		s = strlist_scan(s, tmp);
		if (*tmp == '\0')
			break;
		for (i = 0; i < ARRAY_UNIT(built_key); i++)
			if (strcmp(built_key[i].name, tmp) == 0) {
				array[count++] = built_key[i].value;
				break;
			}
		if (i >= ARRAY_UNIT(built_key)) {
			array[count++] = strtol(tmp, &end, 0);
			if (*end != '\0')
				return 0;
		}
	}

	return count;
}

static int section_getint(const dictionary * d, const char * section, const char * key, int notfound)
{
	const char *str;
	int in[2];

	str = section_getstring(d, section, key, NULL);
	if (strings_int(str, in, 2) == 1)
		return in[0];
	else
		return notfound;
}

/*
 * ------------- Intel byte order --------------------
 *
 *        bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
 * Byte0   4    3    2    1    0    x    x    x
 * Byte1   x    x    x    x    8    7    6    5
 *
 * ------------- Motorola byte order -----------------
 *
 *        bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
 * Byte0   x    x    x    x    8    7    6    5
 * Byte1   4    3    2    1    0    x    x    x
 * ---------------------------------------------------
 */
 


int    open_signal_cfg(const char *cfgname, struct signal_operations *op)
{
	struct sig_global *handle;
	dictionary  *ini;
	sig_cfg_t *cfg;
	struct car_hard_param param;
	int sigs, i, j;
	const char *str;
	int capacity;
	int temp[64];
	int left_hard = -1, right_hard = -1, can_exist = 0;
	int ctrl_msg1, ctrl_msg2;

	if (cfgname == NULL || *cfgname == '\0')
		return -1;
	
	/* 全局配置初始化 */
	handle = &signal_common;
	#ifndef WIN32
	pthread_mutex_init(&handle->signal_mutex, NULL);
    #endif
	handle->valid      = 0;
	handle->no_can     = 0;
	handle->canbox_valid = 0;
	handle->can_detect_delay = CAN_DETECT_DELAY;
	handle->sig_count = 0;
	handle->cfg_list   = NULL;
	handle->can_alive_counter = 0;
	handle->hard_valid = 0;
	handle->hard_left  = NULL;
	handle->hard_right = NULL;
	handle->hard_brake = NULL;
	handle->hard_speed = NULL;
	handle->extern_msg_count = 0;
	
	if (op != NULL)
        handle->sig_op = *op;
	else
		memset(&handle->sig_op, 0, sizeof(handle->sig_op));
	
	ini = xmlparser_load(cfgname);
	if (ini == NULL) {
        pr_err("open %s error\n", cfgname);
		return -1;
	}

	if (xmlparser_find_entry(ini, "global") == 0) {
		pr_err("%s: global secotion do not exist\n", cfgname);
		goto err1;
	}
	str = xmlparser_getstring(ini, "global:order", NULL);
	if (str == NULL) {
		pr_err("%s: global:order do not exist\n", cfgname);
		goto err1;
	}
	if (strcmp(str, "little-endian") == 0)
		handle->big_endian = 0;
	else if (strcmp(str, "big-endian") == 0)
		handle->big_endian = 1;
	else {
		pr_err("%s: global:order error\n", cfgname);
		goto err1;
	}

	handle->bitrate = xmlparser_getint(ini, "global:bitrate", 0);
	if (handle->bitrate <= 0) {
		pr_err("%s: global:bitrate error\n", cfgname);
		goto err1;
	}
	
	handle->boxid = xmlparser_getint(ini, "global:boxid", 0xFFFFFFFFu);
	if (handle->boxid != 0xFFFFFFFFu) {
		if (handle->boxid > 0x7FF || handle->boxid == CTRL_MSG1 || handle->boxid == CTRL_MSG2) {
			pr_err("%s: boxid conflict with control msg or not stand data msg\n", cfgname);
		    goto err1;
		}
		handle->canbox_valid = 1;
	}
	
	/* 获取外挂的CAN ID, 接收到这些报文时需要外挂程序处理 */
    str = xmlparser_getstring(ini, "global:stdlist", NULL);  /* 标准数据帧列表 */
	capacity = strings_int(str, temp, EXTERN_MSGS);
	if (capacity > 0) {
		for (i = 0; i < capacity; i++)
			handle->extern_msgs[i] = (uint32_t)temp[i];
		can_exist = 1;
	}
	
	str = xmlparser_getstring(ini, "global:extlist", NULL);  /* 扩展数据帧列表 */
	j = strings_int(str, temp, EXTERN_MSGS - capacity);
	if (j > 0) {
		for (i = 0; i < j; i++)
			handle->extern_msgs[i+capacity] = (uint32_t)temp[i] | 0x80000000;
		can_exist = 1;
	}
    handle->extern_msg_count = capacity + j;
	
	sigs = sizeof(keystring) / sizeof(keystring[0]);
	handle->sig_count = 0;
	handle->cfg_list = (sig_cfg_t*)malloc(sizeof(sig_cfg_t) * sigs);
	if (handle->cfg_list == NULL)
		goto err1;
    memset(handle->cfg_list, 0, sizeof(sig_cfg_t) * sigs);
	cfg = handle->cfg_list; 
	
    for (i = 0; i < sigs; i++)
	{
		cfg->status = 0;

		if (keystring[i].val_p == NULL) {
			pr_err("%s: the address of the signal variable is invalid\n", keystring[i].sig_name);
			goto err2;
		}

		*(keystring[i].val_p) = keystring[i].default_value;  /* 设置缺省值 */
		if (xmlparser_find_entry(ini, keystring[i].sig_name) == 0)
			continue;
		cfg->val_p = keystring[i].val_p;
		cfg->status = keystring[i].init_status;	

		cfg->invalid_value = keystring[i].default_value;  /* 无效值设置为缺省值 */
        *(cfg->val_p) = keystring[i].default_value;       /* 初始值设置为缺省值 */
        
		if (strcmp(keystring[i].sig_name, "ldw_on") == 0 ||
			strcmp(keystring[i].sig_name, "fcw_on") == 0) {
			cfg->invalid_value = 1;
			*(cfg->val_p) = 1;
		} 
		
		/* 判断信号采用硬线，标准数据帧还是扩展数据帧 */
		if (section_getint(ini, keystring[i].sig_name, "hard", 0) > 0) {  
			cfg->status |= SIG_HARD_LINE;
			cfg->id = 0xFFFFFFFFu;
			if (strcmp(keystring[i].sig_name, "left_light") == 0) 
				handle->hard_left = cfg;
			else if (strcmp(keystring[i].sig_name, "right_light") == 0)
				handle->hard_right = cfg;
			else if (strcmp(keystring[i].sig_name, "brake") == 0)
				handle->hard_brake = cfg;
			else if (strcmp(keystring[i].sig_name, "speed") == 0)
				handle->hard_speed = cfg;
			else {
				pr_err("%s: hard line undefined\n", keystring[i].sig_name);
			    goto err2;
			}
			handle->hard_valid = 1;
		} else if ( (cfg->id = section_getint(ini, keystring[i].sig_name, "stdid", 0xFFFFFFFFu) ) != 0xFFFFFFFFu) {
			can_exist = 1;
		} else if ( (cfg->id = section_getint(ini, keystring[i].sig_name, "extid", 0xFFFFFFFFu) ) != 0xFFFFFFFFu) {
			cfg->id |= 0x80000000u;
			can_exist = 1;
		} else {
			pr_err("%s: no valid can id and hard line\n", keystring[i].sig_name);
			goto err2;
		}

        if ((cfg->status & SIG_HARD_LINE) == 0) {
		    cfg->startbit = section_getint(ini, keystring[i].sig_name, "startbit", -1);
		    cfg->bits = section_getint(ini, keystring[i].sig_name, "bits", -1);
		    if (cfg->startbit < 0 || cfg->bits < 1 || cfg->bits > 16) {
			    pr_err("%s: error startbit or bit length\n", keystring[i].sig_name);
			    goto err2;
		    }

		    if (cfg->bits <= 8) {
			    if ( ( (cfg->startbit & 7) + cfg->bits) > 8) {
			        pr_err("%s: error startbit\n", keystring[i].sig_name);
			        goto err2;
			    }
		    } else if ( ( (cfg->startbit & 7) + cfg->bits) > 16) {
			    pr_err("%s: error startbit\n", keystring[i].sig_name);
			    goto err2;
		    } else if (handle->big_endian == 0) {
			    if ( (cfg->startbit / 8) > 6) {
			        pr_err("%s: error startbit\n", keystring[i].sig_name);
			        goto err2;
			    }
		    } else {
			    if ( (cfg->startbit / 8) == 0) {
			        pr_err("%s: error startbit\n", keystring[i].sig_name);
			        goto err2;
			    }
		    }
		    
		    if ( (cfg->timeout = section_getint(ini, keystring[i].sig_name, "timeout", -1)) < 0) {
			    pr_err("%s: error timeout\n", keystring[i].sig_name);
			    goto err2;
		    }
	    }  	
		
		if (cfg->status & SIG_ANALOG) {  /* 模拟信号 */
			cfg->offset = section_getint(ini, keystring[i].sig_name, "offset", 0);
			cfg->min = section_getint(ini, keystring[i].sig_name, "min", INT_MIN);
			cfg->max = section_getint(ini, keystring[i].sig_name, "max", INT_MAX);
			cfg->mult = section_getint(ini, keystring[i].sig_name, "mult", 1);
			cfg->div = section_getint(ini, keystring[i].sig_name, "div", 1);
			if (cfg->min == INT_MIN || cfg->max == INT_MAX || cfg->min >= cfg->max) {
				pr_err("%s: error param for continuous signal (min, max, mult, div)\n", keystring[i].sig_name);
			    goto err2;
			}
			if (section_getint(ini, keystring[i].sig_name, "signed", 0) > 0)
				cfg->status |= SIG_SIGNED; 
		} else { /* 数字信号 */
			cfg->flash_interval = section_getint(ini, keystring[i].sig_name, "flash", 0);
			if (cfg->flash_interval > 0) 
				cfg->status |= SIG_FLASH; 
			
			if (cfg->status & SIG_HARD_LINE) {
				handle->sig_count++;
		        cfg++;
				continue;	
			}
			
			str = section_getstring(ini, keystring[i].sig_name, "inlist", NULL);
			if (str == NULL) {
				pr_err("%s: missing inlist\n", keystring[i].sig_name);
			    goto err2;
			}
			
			capacity = strings_int(str, cfg->inlist, LIST_COUNT);
			if (capacity < 2) {
				pr_err("%s: invalid inlist\n", keystring[i].sig_name);
			    goto err2;
			}			
			cfg->list_count = capacity;

			str = section_getstring(ini, keystring[i].sig_name, "outlist", NULL);
			if (str == NULL) {
				pr_err("%s: missing outlist\n", keystring[i].sig_name);
			    goto err2;
			} 
			capacity = strings_int(str, cfg->outlist, capacity);
			if (capacity != cfg->list_count) {
				pr_err("%s: invalid outlist\n", keystring[i].sig_name);
			    goto err2;
			}
		}
		handle->sig_count++;
		cfg++;
	}
	
	/* 检查外挂的ID是否与信号ID冲突 */
	for (i = 0; i < handle->extern_msg_count; i++)
		for (j = 0; j < handle->sig_count; j++)
			if (handle->extern_msgs[i] == handle->cfg_list[j].id) {
				pr_err("The conflict between Plug ID and Signal ID\n");
				goto err2;
			}
			
    /* 检查管理报文ID是否与其他报文冲突 */
	if (handle->canbox_valid) {
		ctrl_msg1 = 0;
	    ctrl_msg2 = 0;
	    for (i = 0; i < handle->extern_msg_count; i++)
		    if (handle->extern_msgs[i] == CTRL_MSG1)
			    ctrl_msg1 = 1;

	    for (i = 0; i < handle->sig_count; i++)
		    if (handle->cfg_list[i].id == CTRL_MSG2)
			    ctrl_msg2 = 1;
		
		if (ctrl_msg1 == 0)
			handle->ctrl_id = CTRL_MSG1;
		else if (ctrl_msg2 == 0)
			handle->ctrl_id = CTRL_MSG2;
		else {
			pr_err("The conflict between control msg ID and other ID\n");
			goto err2;
		}
	}
			
	if (handle->hard_valid) {
		if (handle->sig_op.hard_line_init == NULL ||
		    handle->sig_op.get_hard_line == NULL) {
			pr_err("Lack of hard operating function\n");
			goto err2;
		}
		memset(&param, 0, sizeof(param));
		if (handle->hard_left != NULL && (handle->hard_left->status & SIG_FLASH) )
			param.left_flash_interval = handle->hard_left->flash_interval;
		if (handle->hard_right != NULL && (handle->hard_right->status & SIG_FLASH) )
			param.right_flash_interval = handle->hard_right->flash_interval;

		if (handle->sig_op.hard_line_init(&param)) {
			pr_err("Init Hard line device error \n");
			goto err2;
		}
	}
	if (can_exist == 0)
		handle->no_can = 1;
    handle->valid = 1;
	xmlparser_freedict(ini);
	return 0;

err2:
	handle->sig_count = 0;
	free(handle->cfg_list);
	handle->cfg_list = NULL;
err1:
	xmlparser_freedict(ini);
	return -1;
}

void    close_signal_cfg(void)
{
	struct sig_global *handle = &signal_common;

	if (handle->valid <= 0)
		return;
		
	pthread_mutex_lock(&signal_common.signal_mutex);
    handle->valid = 0;

	if (handle->hard_valid && handle->sig_op.hard_line_release != NULL)
		handle->sig_op.hard_line_release();

	handle->sig_count = 0;
	free(handle->cfg_list);
	handle->cfg_list = NULL;
	pthread_mutex_unlock(&signal_common.signal_mutex);
}



struct signal_ctrl*     get_signal_ctrl(void)
{
	struct signal_ctrl* ctrl;
	sig_cfg_t *cfg;
	int i, j, cnt;
	struct sig_global *handle = &signal_common;

	if (handle->valid == 0)
        return NULL;
    
    ctrl = (struct signal_ctrl*)malloc(sizeof(struct signal_ctrl));
    if (ctrl == NULL)
    	return NULL;
    
    ctrl->bitrate = (handle->canbox_valid)? 500000 : handle->bitrate;	
	cnt = 0;
	cfg = handle->cfg_list;
	for (i = 0; i < handle->sig_count; i++, cfg++) 
	{
		for (j = 0; j < cnt; j++)
		{
			if (cfg->id == ctrl->id_tab[j]) break;
		}

		if (j >= cnt)
		{
			ctrl->id_tab[cnt] = cfg->id;
			cnt++;
			if (cnt >= ARRAY_UNIT(ctrl->id_tab)) break;
		}
	}
	
	for (i = 0; i < handle->extern_msg_count; i++) 
	{
		for (j = 0; j < cnt; j++)
		{
			if (handle->extern_msgs[i] == ctrl->id_tab[j]) break;
		}

		if (j >= cnt)
		{
			ctrl->id_tab[cnt] = handle->extern_msgs[i];
			cnt++;
			if (cnt >= ARRAY_UNIT(ctrl->id_tab)) break;
		}
	}
	
	if (handle->canbox_valid) {
		if (cnt < ARRAY_UNIT(ctrl->id_tab))
		    ctrl->id_tab[cnt++] = handle->ctrl_id;
		for (i = 0; i < cnt; i++)
		    if (ctrl->id_tab[i] == handle->boxid)
				break;
		if (i == cnt && cnt < ARRAY_UNIT(ctrl->id_tab))
			ctrl->id_tab[cnt++] = handle->boxid;
	}

	ctrl->id_num = cnt;

	return ctrl;
}



void    can_parser(uint32_t id, uint8_t *dat)
{
	sig_cfg_t *cfg;
	int i, j, signal, def;
	int index, shift;
	unsigned char buf[16];

	if (signal_common.valid == 0)
        return;	
	
	/* 收到CAN转接盒的握手报文, 发送配置报文 */
	if (signal_common.canbox_valid && signal_common.ctrl_id == id &&
	   signal_common.sig_op.can_write != NULL && memcmp(dat, "JIMU", 4) == 0) {
		memset(buf, 0, 8);
		buf[0] = 0x5a;
		buf[1] = signal_common.bitrate / 5000;
		buf[2] = signal_common.boxid;
		buf[3] |= (signal_common.boxid >> 8) & 7;
		if (signal_common.big_endian)
			buf[3] |= 8;
		signal_common.sig_op.can_write(signal_common.ctrl_id, buf, 8);
		return;
	}
	
	pthread_mutex_lock(&signal_common.signal_mutex);  /* 上锁 */
    signal_common.can_alive_counter = CAN_ALIVE_TIMEOUT;
	
	for (i = 0; i < signal_common.extern_msg_count; i++)
		if (id == signal_common.extern_msgs[i]) {
			pthread_mutex_unlock(&signal_common.signal_mutex);
			if (signal_common.sig_op.msg_hook != NULL)
			    signal_common.sig_op.msg_hook(id, dat);  /* 外部处理函数, 不需要加锁 */	
			return;
		}
	   	
	cfg = signal_common.cfg_list;
	for (i = 0; i < signal_common.sig_count; i++, cfg++) 
	{
		/* 判断数据帧类型和ID是否匹配 */
		if (cfg->id != id)
			continue;
		
		/* 获取信号原始值 */
		index = cfg->startbit >> 3;
		shift = cfg->startbit & 7;
		signal  = dat[index] >> shift;
		if (cfg->bits <= 8) {
			;
		} else if (signal_common.big_endian == 0) {
			signal |= dat[index + 1] << (8 - shift);
		} else {
			signal |= dat[index - 1] << (8 - shift);
		}
		signal &= (1 << cfg->bits) - 1;

        if (cfg->status & SIG_ANALOG) { /* 连续信号 */
        	if ( (cfg->status & SIG_SIGNED) && (signal & (1u << (cfg->bits - 1) ) ) )
				signal |= (~0u) << cfg->bits;
			if (signal < cfg->min || signal > cfg->max)
				signal = cfg->invalid_value;
			else
				signal = (signal + cfg->offset) * cfg->mult / cfg->div;
        } else { /* 离散信号 */
        	def = cfg->invalid_value;
			for (j = 0; j < cfg->list_count; j++)
			{
				if (cfg->inlist[j] == signal) {
					signal = cfg->outlist[j];
					break;
				}
				
				if (cfg->inlist[j] == other)  /* 输入信号为其他值时 */
					def = cfg->outlist[j];
			}
			if (j >= cfg->list_count)
				signal = def;
		} 

		if (cfg->status & SIG_FLASH) {
			if (signal > 0) {
				*(cfg->val_p) = signal;
				cfg->flash_counter = cfg->flash_interval;
			} else if (cfg->flash_counter <= 0) {
				*(cfg->val_p) = signal;
			}
		} else {
			if ( (cfg->status & SIG_ANALOG) || signal != keep)  /* 输入信号为模拟量或信号值需要维持不变 */
		        *(cfg->val_p) = signal;
		}
		
		cfg->current_counter = cfg->timeout;
	}

	/* 解锁 */
	pthread_mutex_unlock(&signal_common.signal_mutex);
}


void    can_timeout(int timeout_ms)
{
	sig_cfg_t *cfg;
	int i;

	if (signal_common.valid == 0)
        return;

	cfg = signal_common.cfg_list;
	pthread_mutex_lock(&signal_common.signal_mutex);
	for (i = 0; i < signal_common.sig_count; i++, cfg++)
	{
		if (cfg->current_counter > 0) {
			cfg->current_counter -= timeout_ms;
			if (cfg->current_counter <= 0) {
				*(cfg->val_p) = cfg->invalid_value;
				cfg->flash_counter = 0;
			}
		}
		
		if (cfg->flash_counter > 0) {
			cfg->flash_counter -= timeout_ms;
			if (cfg->flash_counter <= 0)
				*(cfg->val_p) = 0;
		}
	}
	if (signal_common.can_alive_counter > 0)
		signal_common.can_alive_counter -= timeout_ms;
	if (signal_common.can_detect_delay > 0)
		signal_common.can_detect_delay -= timeout_ms;
	pthread_mutex_unlock(&signal_common.signal_mutex);	
	
	if (signal_common.extern_msg_count > 0 && signal_common.sig_op.msg_hook_timeout != NULL)
	    signal_common.sig_op.msg_hook_timeout(timeout_ms);  /* 外部处理函数, 不需要加锁 */
}



int    can_get_input(signal_t *sig)
{
	struct sig_global *handle = &signal_common;
	struct car_hard_signal signal;
	
	if (signal_common.valid == 0)
        return -1;
    if (handle->hard_valid && handle->sig_op.get_hard_line != NULL &&
    	handle->sig_op.get_hard_line(&signal) == 0) {
    	if (handle->hard_left)
    		*handle->hard_left->val_p = signal.left_light;
    	if (handle->hard_right)
    		*handle->hard_right->val_p = signal.right_light;
    	if (handle->hard_brake)
    		*handle->hard_brake->val_p = signal.brake;
    	if (handle->hard_speed) 
    		*handle->hard_speed->val_p = signal.speed * handle->hard_speed->mult / handle->hard_speed->div;
    }
    pthread_mutex_lock(&signal_common.signal_mutex);
    *sig = car_signal;
    pthread_mutex_unlock(&signal_common.signal_mutex);
	return 0;
}


int    can_is_alive(void)
{
	if (signal_common.valid == 0)
		return 0;
	if (signal_common.can_alive_counter > 0)
		return 1;
	return 0;
}

int    can_is_outline(void)
{
	if (signal_common.valid == 0 || 
	    signal_common.no_can != 0 ||
		signal_common.can_detect_delay > 0 ||
		signal_common.can_alive_counter > 0)
		return 0;

	return 1;
}

unsigned char  get_caninput_version(void)
{
	return CANI_VERSION;
}

/*****************************************************/
/**
 * Function:	 get_can_record
 *
 * Description:	 获取CAN报文记录, 每个报文占用12字节，连续存放。
 *               前4字节为ID，小端存放，后8字节为数据
 *
 * Parameters:	 buffer      - 保存CAN报文的缓冲区
 *               buffer_size - 缓冲区大小
 *
 * Return:		 读取的字节数
 *
 * History:		
 * - V1.0, 2017.12.20, LanLong
 *     Initial
 */

